package sf.querydsl.dao;

import com.querydsl.core.types.Predicate;
import com.querydsl.sql.AbstractSQLQuery;
import com.querydsl.sql.Configuration;
import com.querydsl.sql.SQLTemplates;
import com.querydsl.sql.dml.SQLDeleteClause;
import com.querydsl.sql.dml.SQLInsertClause;
import com.querydsl.sql.dml.SQLMergeClause;
import com.querydsl.sql.dml.SQLUpdateClause;
import sf.common.wrapper.Page;
import sf.core.DBObject;
import sf.database.dao.DBClient;
import sf.database.jdbc.sql.Crud;
import sf.database.util.DBUtils;
import sf.querydsl.QueryDSLDialectUtils;
import sf.spring.util.Assert;

import javax.inject.Provider;
import java.sql.Connection;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Stream;

public class DBQueryDSLImpl implements DBQueryDSL {

    protected DBClient client;

    public DBQueryDSLImpl(DBClient client) {
        this.client = client;
    }

    @Override
    public SQLTemplates queryDSLSQLTemplates(boolean readonly) {
        return client.executeFunc(conn -> QueryDSLDialectUtils.getSQLTemplates(DBUtils.doGetDialect(conn, false).getQueryDslDialect()));
    }

    @Override
    public Configuration queryDSLConfiguration(Class<? extends DBObject>... tableClass) {
        return client.executeFunc(conn -> Crud.getInstance().getQueryDSLInf().queryDSLConfiguration(conn, tableClass));
    }

    @Override
    public Provider<Connection> queryDSLProvider(boolean readonly) {
        throw new UnsupportedOperationException("not support!");
    }

    @Override
    public <T extends DBObject> boolean queryDSLExists(List<Predicate> predicates, Class<T> clz) {
        Assert.notNull(predicates, "返回类型不能为空");
//        Class<?> clz = QueryDSL.getQueryDSLTableClass(query);
        return client.executeFunc(conn -> Crud.getInstance().getQueryDSLInf().queryDSLExists(conn, predicates, clz));
    }

    @Override
    public <T> List<T> queryDSLSelectList(AbstractSQLQuery<?, ?> query, Class<T> returnClass) {
        Assert.notNull(returnClass, "返回类型不能为空");
//        Class<?> clz = QueryDSL.getQueryDSLTableClass(query);
        return client.executeFunc(conn -> Crud.getInstance().getQueryDSLInf().queryDSLSelectList(conn, query, returnClass));
    }

    @Override
    public <T> Page<T> queryDSLSelectPage(AbstractSQLQuery<?, ?> query, Class<T> returnClass, long start, int limit) {
        Assert.notNull(returnClass, "返回类型不能为空");
//        Class<?> clz = QueryDSL.getQueryDSLTableClass(query);
        return client.executeFunc(conn -> Crud.getInstance().getQueryDSLInf().queryDSLSelectPage(conn, query, returnClass, start, limit));
    }

    @Override
    public <T> T queryDSLSelectOne(AbstractSQLQuery<?, ?> query, Class<T> returnClass) {
        Assert.notNull(returnClass, "返回类型不能为空");
//        Class<?> clz = QueryDSL.getQueryDSLTableClass(query);
        return client.executeFunc(conn -> Crud.getInstance().getQueryDSLInf().queryDSLSelectOne(conn, query, returnClass));
    }

    @Override
    public <T> void queryDSLSelectIterator(Consumer<Iterable<T>> ormIt, Class<T> beanClass, AbstractSQLQuery<?, ?> query) {
        Assert.notNull(beanClass, "返回类型不能为空");
//        Class<?> clz = QueryDSL.getQueryDSLTableClass(query);
        client.executeFunc(conn -> {
            Crud.getInstance().getQueryDSLInf().selectIterator(conn, ormIt, query, beanClass);
            return null;
        });
    }

    @Override
    public <T> void queryDSLSelectStream(Consumer<Stream<T>> ormStream, Class<T> beanClass, AbstractSQLQuery<?, ?> query) {
        Assert.notNull(beanClass, "返回类型不能为空");
//        Class<?> clz = QueryDSL.getQueryDSLTableClass(query);
        client.executeFunc(conn -> {
            Crud.getInstance().getQueryDSLInf().selectStream(conn, ormStream, query, beanClass);
            return null;
        });
    }

    @Override
    public int queryDSLInsert(SQLInsertClause insert) {
        Class<?> clz = null;
//        clz = QueryDSL.getInsertTableClass(insert);
        return client.executeFunc(conn -> Crud.getInstance().getQueryDSLInf().queryDSLInsert(conn, insert));
    }

    @Override
    public int queryDSLInsert(SQLInsertClause insert, List<Map<String, Object>> keyValues) {
        Class<?> clz = null;
//        clz = QueryDSL.getInsertTableClass(insert);
        return client.executeFunc(conn -> Crud.getInstance().getQueryDSLInf().queryDSLInsert(conn, insert, keyValues));
    }

    @Override
    public int queryDSLUpdate(SQLUpdateClause update) {
        Class<?> clz = null;
//        clz = QueryDSL.getUpdateTableClass(update);
        return client.executeFunc(conn -> Crud.getInstance().getQueryDSLInf().queryDSLUpdate(conn, update));
    }

    @Override
    public int queryDSLDelete(SQLDeleteClause delete) {
        Class<?> clz = null;
//        clz = QueryDSL.getDeleteTableClass(delete);
        return client.executeFunc(conn -> Crud.getInstance().getQueryDSLInf().queryDSLDelete(conn, delete));
    }

    @Override
    public int queryDSLMerge(SQLMergeClause merge) {
        Class<?> clz = null;
//        clz = QueryDSL.getMergeTableClass(merge);
        return client.executeFunc(conn -> Crud.getInstance().getQueryDSLInf().queryDSLMerge(conn, merge));
    }

    @Override
    public int queryDSLMerge(SQLMergeClause merge, List<Map<String, Object>> keyValues) {
        Class<?> clz = null;
//        clz = QueryDSL.getMergeTableClass(merge);
        return client.executeFunc(conn -> Crud.getInstance().getQueryDSLInf().queryDSLMerge(conn, merge, keyValues));
    }
}
